﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BLL;
using System.Threading;
using common;
using System.Collections;
using System.Xml;
using Model;
using System.Messaging;

namespace BLL.MailSend
{
    public class SendMailServiceOperation:IDisposable
    {
        MyEventArgs args = new MyEventArgs();   //事件参数
        public event D_CallBack PutOutInfomation;

        private Mutex mutex=new Mutex();
        private static wk_Queue myQueue = new wk_Queue();  //内存队列 用于缓冲数据
        private int threadCount =Int32.Parse( System.Configuration.ConfigurationManager.AppSettings["ThreadCount"].ToString());
        private int threadSleep = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["SLEEP"].ToString());
        //private static object obj=new object();  //局部对象锁
        //private BLLsmsmt smsmt = new BLLsmsmt(); //数据库操作类。


        private string messageId = string.Empty;
        private string text = string.Empty;

        public static bool readThreadFlag = false;
        public static bool writeThreadFlag = false;
        public delegate void mydelegate(object state);
        static object srcLock = new object();
        static object msgLock = new object();
        static object writeLock = new object();

        #region 获取状态
        public static bool getReadThreadFlag()
        {
            return readThreadFlag;
        }

        public static bool getWriteThreadFlag()
        {
            return writeThreadFlag;
        }

        //设置发送线程退出
        public static void setReadThreadFlag()
        {
            readThreadFlag = true;
        }

        //设置接收消息队列线程退出
        public static void setThreadFlag()
        {
            writeThreadFlag = true;
        }

        //获取状态队列中的条数,
        public static string getQueueState()
        {
            string temp = string.Empty;
            temp = "" + myQueue.Count +"$"+myQueue.ReadCount+"$"+myQueue.WriteCount;
            return temp;
        }
        #endregion

        #region 构造函数
        public SendMailServiceOperation()
        {
        }
        #endregion

        #region work run it
        /// <summary>
        /// 开始工作
        /// </summary>
        public void Run()
        {
            try
            {
                //读取点播队列线程.
                Thread addListThread01 = new Thread(new ParameterizedThreadStart(ReceiveWork));
                addListThread01.Name = "读取点播队列";
                addListThread01.Priority = ThreadPriority.Highest;
                addListThread01.IsBackground = true;
                addListThread01.Start("MSMQPathSend02");

                //读取群发队列线程.
                Thread addListThread = new Thread(new ParameterizedThreadStart(ReceiveWork));
                addListThread.Name = "读取群发队列";
                addListThread.IsBackground = true;
                addListThread.Start("MSMQPathSend01");

                //发送线程.
                //Thread outListThread = new Thread(new ParameterizedThreadStart(SendSmsWork));
                //outListThread.IsBackground = true;
                //outListThread.Start();

                //发送线程组。
                //System.Threading.WaitCallback waitcal = new System.Threading.WaitCallback(SendSmsWork);
                for (int i = 0; i < threadCount; i++)
                {
                    //ThreadPool.QueueUserWorkItem(waitcal);

                    ///////////////
                    //发送线程.
                    Thread outListThread = new Thread(new ParameterizedThreadStart(SendSmsWork));
                    outListThread.Name = "工作线程" + (i + 1).ToString();
                    outListThread.IsBackground = true;
                    outListThread.Start();
                }
            }
            catch (Exception ex)
            {
                Thread.Sleep(1000);
                throw ex;
            }
        }
        #endregion

        #region 发送消息
        public void SendSmsWork(object state)
        {
            using (MSMQHelper ms = new MSMQHelper("MSMQPathSmsErr"))
            {
                int n;
                while (true)
                {
                    if (readThreadFlag)
                    {
                        Thread.CurrentThread.Abort();
                    }
                    else
                    {
                        n = 0;
                        //lock (this)
                        {
                            n = myQueue.Count;
                        }

                        if (n > 0)
                        {
                            mutex.WaitOne();
                            Usr msg = (Usr)myQueue.outQueue();
                            mutex.ReleaseMutex();

                            if (msg != null)
                            {
                                //组合鉴权信息
                                //mysoapheader.spId = System.Configuration.ConfigurationManager.AppSettings["spid"].ToString();
                                //mysoapheader.timeStamp = DateTime.Now.ToString("MMddHHmmss");
                                //mysoapheader.spPassword = common.CommMethod.MD5Encrypt(mysoapheader.spId + pwd + mysoapheader.timeStamp);

                                //sendSms sms = new sendSms();
                                //overrideSms(ref msg);                    //组合消息头.
                                //overrideSendSms(ref sms, ref msg);           //组合完整消息
                                //service.soaphader = mysoapheader;
                                //sendSmsResponse myresponse = new sendSmsResponse();

                                //发送消息
                                //try
                                //{
                                //    insertSmsmt(msg);
                                //    myresponse = service.sendSms(sms);  //发送消息

                                //    // 将下发结果result保存到数据库SMSMT表，result 字段
                                //    BLLsmsmt.UpdateResult(myresponse.result, msg.Mt.PKTotal);
                                //}
                                //catch (System.Web.Services.Protocols.SoapException soapEx)  //处理电信反馈的异常。
                                //{
                                //    #region 处理异常
                                //    bool forflag = true;
                                //    int x = 11;

                                //    while (forflag)
                                //    {
                                //        x--;
                                //        handlingExcetpion(soapEx, msg);
                                //        //try
                                //        //{
                                //        //    Thread.Sleep(threadSleep);

                                //        //    //组合鉴权信息
                                //        //    mysoapheader.spId = System.Configuration.ConfigurationManager.AppSettings["spid"].ToString();
                                //        //    mysoapheader.timeStamp = DateTime.Now.ToString("MMddHHmmss");
                                //        //    mysoapheader.spPassword = common.CommMethod.MD5Encrypt(mysoapheader.spId + pwd + mysoapheader.timeStamp);
                                //        //    if (x == 0)
                                //        //    {
                                //        //        break;
                                //        //    }
                                //        //    myresponse = service.sendSms(sms);
                                //        //    BLLsmsmt.UpdateResult(myresponse.result, msg.Mt.PKTotal);

                                //        //    forflag = false;
                                //        //}catch(System.Web.Services.Protocols.SoapException soapEx1)
                                //        //{
                                //        //    handlingExcetpion(soapEx1, msg);
                                //        //    forflag = true;
                                //        //}
                                //    }
                                    
                                //    #endregion
                                //}
                                //catch(Exception ex) //需要处理异常 可能超时。
                                //{
                                //    #region 处理异常

                                //    args.Object_I = ex.Message;
                                //    this.PutOutInfomation(this, args);
                                //    Thread.Sleep(30000);


                                //    bool forflag = true;

                                //    while (forflag)
                                //    {
                                //        try
                                //        {
                                //            Thread.Sleep(threadSleep);

                                //            ////组合鉴权信息
                                //            //mysoapheader.spId = System.Configuration.ConfigurationManager.AppSettings["spid"].ToString();
                                //            //mysoapheader.timeStamp = DateTime.Now.ToString("MMddHHmmss");
                                //            //mysoapheader.spPassword = common.CommMethod.MD5Encrypt(mysoapheader.spId + pwd + mysoapheader.timeStamp);

                                //            //myresponse = service.sendSms(sms);
                                //            //BLLsmsmt.UpdateResult(myresponse.result, msg.Mt.PKTotal);

                                //            forflag = false;
                                //        }
                                //        catch (Exception myex)
                                //        {
                                //            args.Object_I = myex.Message;
                                //            this.PutOutInfomation(this, args);

                                //            Thread.Sleep(30000);
                                //            forflag = true;
                                //        }
                                //    }
                                //    #endregion
                                //}
                                //Console.WriteLine(msg.Mt.Msg);
                            }
                            msg = null;
                        }
                        Thread.Sleep(threadSleep);
                    }
                }
            }
        }

        ///// <summary>
        ///// 处理异常 
        ///// </summary>
        ///// <param name="soapEx"></param>
        ///// <param name="msg"></param>
        //private void handlingExcetpion(System.Web.Services.Protocols.SoapException soapEx,SMSMsg msg)
        //{
        //    XmlDocument doc = new XmlDocument();
        //    doc.LoadXml(soapEx.Detail.OuterXml);
        //    XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
        //    nsManager.AddNamespace("comm3", "http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1");
        //    XmlNode categoryNode;

        //    try
        //    {
        //        categoryNode = doc.DocumentElement.SelectSingleNode("comm3:ServiceException", nsManager);
        //        messageId = categoryNode.SelectSingleNode("messageId", nsManager).InnerText;
        //        text = categoryNode.SelectSingleNode("text", nsManager).InnerText;
        //    }
        //    catch
        //    {
        //        categoryNode = doc.DocumentElement.SelectSingleNode("comm3:PolicyException", nsManager);
        //        messageId = categoryNode.SelectSingleNode("messageId", nsManager).InnerText;
        //        text = categoryNode.SelectSingleNode("text", nsManager).InnerText;
        //    }
        //    //将异常写如短信SMSMT表。static
        //    BLLsmsmt.SmsStatic(messageId, text, msg.Mt.PKTotal);
        //}

        /// <summary>
        /// 记录下行记录
        /// </summary>
        /// <param name="msg"></param>
        private void insertSmsmt(SMSMsg msg)
        {
            ////发送消息前先写入一条数据到SMSMT表
            //smsmt model = new smsmt();
            
            //model.areaid = msg.Mt.AreaID;
            //model.region = msg.Mt.Region;

            //model.body = msg.Mt.Msg;
            //model.linkid = msg.Mt.LinkID;

            //if (msg.Mt.MsgFmt == null)
            //{
            //    model.msgfmt = "";
            //}
            //else
            //{
            //    model.msgfmt = msg.Mt.MsgFmt;
            //}
            //model.prdid = msg.Mt.PrdID;
            
            //model.status = "";

            //int inttem;
            //int.TryParse(msg.Mt.FeeCode, out inttem);

            //model.repeatnum = 0;
            //model.pk_number = 0;
            //model.regdel = 0;

            //model.feeusertype = "";
            //model.feecode = inttem;
            //model.feeterminalid = msg.Mt.FeeTerminalId;
            //model.feetype = msg.Mt.FeeType;

            //model.srcid = msg.Mt.SrcAdrr;
            //model.destid = msg.Mt.DestAddr.PhoneID;
            //model.serviceid = msg.Mt.ServiceID.Substring(11,10);
            //model.writetm = DateTime.Now;
            //model.tm = DateTime.Now;
            //model.pk_total = msg.Mt.PKTotal;

            //model.channel = msg.Mt.ChannelId;
            //model.actionID = msg.Mt.ActionID;
            //model.infoid = msg.Mt.InfoID;
            //model.result = "";
            //model.msgid = "";
            //BLLsmsmt.insertSmsMt(model);
        }
        #endregion

        #region 业务实现
        //完善消息头部分.
        public static void overrideSms(ref SMSMsg mtmsg)
        {
            //try
            //{
            //    //来自消息队列自数据库.
            //    //此处为根据消息再生成.
            //    if (mtmsg.Mt.ServiceID == null)
            //    {
            //        mtmsg.Mt.ServiceID = string.Empty;
            //    }
            //    if (mtmsg.Mt.LinkID == null)
            //    {
            //        mtmsg.Mt.LinkID = string.Empty;
            //    }
            //    if (mtmsg.Mt.DestAddr.PhoneID==null)
            //    {
            //        mysoapheader.OA = string.Empty;
            //    }

            //    mysoapheader.productId = mtmsg.Mt.ServiceID;// mtmsg.Mt.ServiceID;       //产品编号  测试编号 108104009010000001529
            //    mysoapheader.linkId = mtmsg.Mt.LinkID;             //事务关联ID 用户点播业务.
            //    mysoapheader.OA = "tel:+86" + mtmsg.Mt.DestAddr.PhoneID;  // " ";         //业务订购地址.

            //    //mysoapheader.SAN = " ";                          //业务接入码
            //    //mysoapheader.transactionId = " ";                //业务流水号
            //    //mysoapheader.transEnd = EndReason.Item1;           //交易终结号.

            //    //mysoapheader.FA = "tel:+86" + mtmsg.Mt.DestAddr[0].PhoneID;
            //    //mysoapheader.FA = mtmsg.Mt.FeeTerminalId;        //付费地址 
            //    //mysoapheader.multicastMessaging = false;         //是否群发? 默认为false
            //}
            //catch (Exception ex)
            //{
            //    CommMethod.insertText("overrideSms()函数异常:" + ex.Message);
            //}
        }

        /// <summary>
        /// 消息在这里组合,组合消息内容,目标地址,源地址.计费类型
        /// </summary>
        /// <param name="sms"></param>
        //public void overrideSendSms(ref sendSms sms,ref SMSMsg msg)
        //{
        //    try
        //    {
        //        if (msg.Mt.Msg == null)
        //        {
        //            msg.Mt.Msg = string.Empty;
        //        }
        //        if (msg.Mt.SrcAdrr == null)
        //        {
        //            msg.Mt.SrcAdrr = string.Empty;
        //        }


        //        //组合短信内容
        //        sms.message = msg.Mt.Msg;
        //        //发送地址
        //        sms.senderName = msg.Mt.SrcAdrr;

        //        //组合计费信息
        //        ChargingInformation cif = new ChargingInformation();
        //        cif.description = "计费描述";
        //        cif.code = msg.Mt.FeeCode.ToString();
        //        cif.amount = decimal.Parse("0");   //计费总金额
        //        cif.currency = "tel:+86" + msg.Mt.FeeTerminalId;
        //        sms.charging = cif;

        //        //组合SimpleReference   是否需要状态报告
        //        SimpleReference simplreference = new SimpleReference();
        //        simplreference.correlator = Guid.NewGuid().ToString("N"); //流水号 SP产生唯一
        //        msg.Mt.PKTotal = simplreference.correlator;             //将流水号加入到SmsMsg的PKTotal字段
        //        //simplreference.endpoint = " ";    // 终结点 地址
        //        simplreference.interfaceName = "SendSmsService";
        //        if (msg.Mt.Msg.Length < 150)       //短信内容长度大于150字 不需要状态报告
        //        {
        //            sms.receiptRequest = simplreference;
        //        }

        //        //组合目标地址
        //        string[] address = new string[1];
        //        for (int i = 0; i < address.Length; i++)
        //        {
        //            address[i] = "tel:+86" + msg.Mt.DestAddr.PhoneID;
        //        }
        //        sms.addresses = address;
        //    }
        //    catch (Exception ex)
        //    {
        //        //触发事件
        //        args.Object_I = ex.Message;
        //        this.PutOutInfomation(this, args);
        //    }
        //}
        #endregion

        #region 读取队列数据到内存队列
        /// <summary>
        ///读取队列数据到内存队列
        /// </summary>
        /// <param name="state"></param>
        public void ReceiveWork(object state)
        {
            //单线程锁.
            while (true)
            {
                //lock (this)
                {
                    try
                    {
                        //线程状态.
                        if (writeThreadFlag)
                        {
                            Thread.CurrentThread.Abort();
                        }
                        else
                        {
                            ReadMSMQ("" + state);   //写缓冲区
                        }
                    }
                    catch (Exception ex)
                    {
                        //writeThreadFlag = true; //不要对线程关闭
                        args.Object_I ="读取工作线程异常: "+ex.Message + "读取给工作线程异常："+state;
                        this.PutOutInfomation(this, args);
                    }
                }
            }
        }

        /// <summary>
        /// 缓冲区长度
        /// </summary>
        private static int buflen = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["Buflen"]);

        /// <summary>
        /// 读取send队列 写入到程序缓冲区。
        /// </summary>
        private static void ReadMSMQ(string stat)
        {
            try
            {
                using (common.MSMQHelper msmq = new common.MSMQHelper(stat))
                {
                    if (myQueue.Count < buflen)
                    {
                        System.Messaging.Message msg = new System.Messaging.Message();
                        msg = msmq.ReceiveObject();
                        if (msg == null)
                        {
                            Thread.SpinWait(10);
                        }
                        else
                        {
                            //msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(MTMSGCont) });
                            msg.Formatter = new ActiveXMessageFormatter();
                            SMSMsg mtmsg = new SMSMsg();
                            //SMSMsg mtmsg =(SMSMsg) MSMQHelper.StringSerializerToObj("" + msg.Body,temSMSmsg.GetType() );
                            StringBuilder body = new StringBuilder();
                            StringBuilder Label=new StringBuilder();
                            Label.Append(msg.Label);
                            body.Append(msg.Body);

                            mtmsg.Mt.AreaID = Label.ToString(2,3).Trim();
                            mtmsg.Mt.Region = Label.ToString(3,4).Trim();

                            mtmsg.Mt.PrdID = body.ToString(0, 4).Trim();
                            mtmsg.Mt.ChannelId = body.ToString(4, 4).Trim();
                            mtmsg.Mt.ActionID = body.ToString(8,1).Trim();
                            mtmsg.Mt.DelStatus = body.ToString(35, 1).Trim();
                            mtmsg.Mt.SrcAdrr = body.ToString(89, 21).Trim();
                            mtmsg.Mt.DestAddr.PhoneID = body.ToString(110, 32).Trim();
                            mtmsg.Mt.LinkID = body.ToString(142, 20).Trim();
                            if (body.ToString(36, 10).Trim().Length==10)
                            {
                                //string tem = body.ToString(36, 10);
                                //if (tem == "0000001533" || tem == "0000001530" || tem == "0000001529" || tem == "0000001551")
                                //{
                                mtmsg.Mt.ServiceID = "10810400901" + body.ToString(36, 10);
                                //}
                                //else
                                //{
                                //    mtmsg.Mt.ServiceID = "10810400902" + body.ToString(36, 10);
                                //}
                            }
                            else
                            {
                                mtmsg.Mt.ServiceID = body.ToString(36, 10);
                            }

                            mtmsg.Mt.Msg = body.ToString(187, body.Length - 187).Trim();

                            mtmsg.Mt.FeeCode = body.ToString(83, 6).Trim();
                            mtmsg.Mt.FeeType = body.ToString(81, 2).Trim();
                            mtmsg.Mt.FeeTerminalId = body.ToString(47, 32).Trim();
                            mtmsg.Mt.InfoID = body.ToString(171,16).Trim();

                            if (mtmsg != null)
                            {
                                lock (writeLock)
                                {
                                    //myQueue.inQueue(mtmsg);  //写入程序缓存区
                                }
                            }
                            Thread.SpinWait(1);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                common.CommMethod.insertText(ex.Message);
                throw ex;
            }
        }
        #endregion

        #region 释放内存
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(true);
        }

        protected virtual void Dispose(bool disposing)
        {

        }
        #endregion
    }
}
